#include "Overlord.h"

namespace XGE
{
    template<> Overlord* Ogre::Singleton<Overlord>::ms_Singleton = 0;

    Overlord* Overlord::getSingletonPtr(void)
    {
        return ms_Singleton;
    }

    Overlord& Overlord::getSingleton(void)
    {
        assert( ms_Singleton );  return ( *ms_Singleton );
    }

    Overlord::Overlord(const Ogre::String& nName)
    {
        strName = nName;
        quit = false;
    }

    Overlord::~Overlord()
    {
        if(!managers.empty())
        {
            XGE::IManagerVec::iterator i;
            for(i = vManagers.begin(); i != vManagers.end(); ++i)
            {
                delete (*i);
            }

            vManagers.clear();
            managers.clear();
        }

        delete root;
    }

    bool Overlord::init()
    {
        //Register the Ogre Root object
        if(!(root = new Ogre::Root))
        {
            return false;
        }

        //Show Config Dialog
        if(!(root->showConfigDialog()))
        {
            return false;
        }

        window = root->initialise(true, strName);

        //Initialize our managers in order
        XGE::IManagerVec::iterator i;
        for(i = vManagers.begin(); i != vManagers.end(); ++i)
        {
            if(!(*i)->init())
            {
                throw(Ogre::Exception(Ogre::Exception::ERR_INTERNAL_ERROR, "\"" + (*i)->getName() + "\" was unable to initialize!", "Overlord.h"));
            }
        }

        return true;
    }

    bool Overlord::addManager(IManager* nMan)
    {
        if(nMan)
        {
            if(!managers[nMan->getName()])
            {
                managers[nMan->getName()] = nMan;
                vManagers.push_back(managers[nMan->getName()]);
                return true;
            }
            else
            {
                throw(Ogre::Exception(Ogre::Exception::ERR_DUPLICATE_ITEM, "Cannot add \"" + nMan->getName() + "\" because a manager with this name already exists!", "Overlord.h"));
            }
        }

        throw(Ogre::Exception(Ogre::Exception::ERR_INVALIDPARAMS, "Cannot add a manager because it is invalid!", "Overlord.h"));
        return false;
    }

    bool Overlord::getManager(Ogre::String nManName)
    {
        if(!managers[nManName])
        {
            throw(Ogre::Exception(Ogre::Exception::ERR_ITEM_NOT_FOUND, "Cannot get \"" + nManName + "\" because it does not exist!", "Overlord.h"));
        }
        else
        {
            return managers[nManName];
        }
    }

    void Overlord::removeManager(Ogre::String nManName)
    {
        if(managers[nManName])
        {
            XGE::IManagerVec::iterator i;
            for(i = vManagers.begin(); i != vManagers.end(); ++i)
            {
                if((*i) == managers[nManName])
                {
                    delete (*i);
                    vManagers.erase(i);
                    break;
                }
            }

            managers.erase(nManName);
        }
        else
        {
            throw(Ogre::Exception(Ogre::Exception::ERR_ITEM_NOT_FOUND, "Cannot delete \"" + nManName + "\" because it does not exist!", "Overlord.h"));
        }
    }

    bool Overlord::execute()
    {
        if(!managers.empty())
        {
            XGE::IManagerVec::iterator i;
            while(!quit)
            {
                Ogre::WindowEventUtilities::messagePump();
                i = vManagers.begin();
                while(i != vManagers.end())
                {
                    if((*i)->_update())
                    {
                        quit = true;
                    }
                }
            }
        }
        else
        {
            throw(Ogre::Exception(Ogre::Exception::ERR_RT_ASSERTION_FAILED, "The Overlord was instructed to Execute() without any registered managers!", "Overlord.cpp"));
        }

        return quit;
    }
}
